package cc.rengu.redp.bizimpl.upmp.service.impl;

import cc.rengu.redp.bizimpl.constant.UpmpConstant;
import cc.rengu.redp.bizimpl.enums.BizDataAuditStatusEnum;
import cc.rengu.redp.bizimpl.enums.BizDataStatusEnum;
import cc.rengu.redp.bizimpl.enums.BizOprEnum;
import cc.rengu.redp.bizimpl.enums.PageOptFlagEnum;
import cc.rengu.redp.bizimpl.upmp.common.BusinessContainer;
import cc.rengu.redp.bizimpl.upmp.dao.FeeInfoMapper;
import cc.rengu.redp.bizimpl.upmp.domain.*;
import cc.rengu.redp.bizimpl.upmp.service.*;
import cc.rengu.redp.bizimpl.upmp.vo.OperationResult;
import cc.rengu.redp.bizimpl.upmp.vo.UpmpUserInfoVO;
import cc.rengu.redp.bizimpl.utils.Common;
import cc.rengu.redp.bizimpl.utils.CommonUtils;
import cc.rengu.redp.bizimpl.utils.DateUtils;
import cc.rengu.redp.bizimpl.utils.GetBeforeDate;
import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.exception.RedpException;
import cc.rengu.redp.common.utils.SortUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 刘玉亮.LL
 */
@Service
public class FeeInfoServiceImpl extends ServiceImpl<FeeInfoMapper, FeeInfo> implements IFeeInfoService {

    @Autowired
    private IUpmpSysParamService upmpSysParamService;
    @Autowired
    private IUpmpOrganizationService organizationService;
    @Autowired
    private IUpmpPrivilegeCheckService upmpPrivilegeCheckService;
    @Autowired
    private IUpmpSysSeqService upmpSysSeqService;
    @Autowired
    private IBizTmpService bizTmpService;
    @Autowired
    private IBizHisService bizHisService;
    @Autowired
    private IUpmpBMchntFeeInfoService bMchntFeeInfoService;
    @Override
    public IPage<FeeInfo> findByPage(QueryRequest request, FeeInfo info) {
        try {
            LambdaQueryWrapper<FeeInfo> queryWrapper = new LambdaQueryWrapper<>();
            UpmpUserInfoVO user = CommonUtils.getCurrentUser(upmpSysParamService);
            String instId = "";
            if (null != user && user.isAdmin()) {
                    instId = info.getInstId();
                if (StringUtils.isBlank(instId)) {
                    instId = user.getInstId();
                }
            } else {
                instId = user.getInstId();
                // queryWrapper.in(FeeInfo::getCrtOrgId, Arrays.asList(GZIPUtils.uncompressToString(user.getUserOrgCodes()).split(",")));
            }
            queryWrapper.eq(FeeInfo::getInstId, instId);
            queryWrapper.inSql(FeeInfo::getId,"select id from t_b_fee_info t1 where not exists(select 1 from t_b_fee_info t2 where t1.fee_cd = t2.fee_cd and t2.id > t1.id  and t2.inst_id = '" + instId + "')");

            if (StringUtils.isNotBlank(info.getFeeCd())) {
                queryWrapper.like(FeeInfo::getFeeCd, info.getFeeCd());
            }
            if (StringUtils.isNotBlank(info.getFeeName())) {
                queryWrapper.like(FeeInfo::getFeeName, info.getFeeName());
            }
            if (StringUtils.isNotBlank(info.getFeeDesc())) {
                queryWrapper.like(FeeInfo::getFeeDesc, info.getFeeDesc());
            }
            Page<FeeInfo> page = new Page<>();
//            SortUtil.handlePageSort(request, page, true);
            SortUtil.handlePageSort(request, page,"feeCd", UpmpConstant.ORDER_DESC, true);
            return this.page(page, queryWrapper);
        } catch (Exception e) {
            log.error("查询失败", e);
            return null;
        }
    }
    @Override
    public List<FeeInfo> findcd(String feecd, String instId) {
        LambdaQueryWrapper<FeeInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FeeInfo::getInstId, instId);
        wrapper.eq(FeeInfo::getFeeCd, feecd);
        wrapper.orderByAsc(FeeInfo::getPSeqNo);
        return this.list(wrapper);
    }
    @Override
    public List<FeeInfo> findallBypCalType(String feecd, String instId) {
        LambdaQueryWrapper<FeeInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FeeInfo::getInstId, instId);
        wrapper.eq(FeeInfo::getFeeCd, feecd);
        wrapper.eq(FeeInfo::getPCalType, "2");
        wrapper.eq(FeeInfo::getImpStatus, BusinessContainer.impStatus_01);
        wrapper.orderByAsc(FeeInfo::getPSeqNo);
        return this.list(wrapper);
    }

    // 查询费率信息（code-name），重复算一条
    @SuppressWarnings("rawtypes")
    @Override
    public Map<String, Object> feeInfoRSelect2List(QueryRequest request, String q) {
        UpmpUserInfoVO user = CommonUtils.getCurrentUser(upmpSysParamService);
        //q的格式为  EQ_instId & CN_feeCd_OR_feeName & EQ_pCalType
        q = q.replaceAll("&amp;", "&");
        if (null == q) {
            return null;
        }
        LambdaQueryWrapper<FeeInfo> wrapper = new LambdaQueryWrapper<>();
        String instId = "";
        String[] param = q.split("&");
        if (null != param && param.length > 0) {
            wrapper.or(wp -> {
                wp.likeRight(FeeInfo::getFeeCd, param[0])
                        .likeRight(FeeInfo::getFeeName, param[0]);
            });
            if (param.length > 1) {
                instId = param[1];
            }
            if (param.length > 2) {
                String pCalType = param[2];
                wrapper.eq(FeeInfo::getPCalType, pCalType);
            } else {
                // 分段方式为：2-固定金额
                wrapper.eq(FeeInfo::getPCalType, "2");
            }
        }

        if (Common.isBlank(instId)) {
            instId = user.getInstId();
        }
        wrapper.eq(FeeInfo::getInstId, instId);
        wrapper.eq(FeeInfo::getImpStatus, BusinessContainer.impStatus_01);
        if (!user.isAdmin()) {
//       wrapper.in(FeeInfo::getCrtOrgId,)GZIPUtils.uncompressToString(user.getUserOrgCodes());
        }
        Page<FeeInfo> page = new Page<>();
        SortUtil.handlePageSort(request, page, true);
        Page<FeeInfo> page1 = this.page(page, wrapper);
        List<FeeInfo> listx = page1.getRecords();
        listx = listx.stream().filter(CommonUtils.distinctByKey(b -> b.getFeeCd() + ";" + b.getFeeName() + ";" + b.getFeeDesc() + ";" + b.getFeeScene())).collect(Collectors.toList());
        Map<String, Object> maps = new HashMap<String, Object>();
        Map<String, String> map = new HashMap<String, String>();
        List<Object> list = new ArrayList<Object>();
        for (int i = 0; i < listx.size(); i++) {
            FeeInfo ai = listx.get(i);
            map = new HashMap<String, String>();
            map.put("id", ai.getFeeCd());
            map.put("name", ai.getFeeName());
            map.put("feeDesc", ai.getFeeDesc());
            map.put("feeScene", ai.getFeeScene());
            list.add(map);
        }
        maps.put("results", list);
        int pageIndex = Common.isBlank(request.getPageNum()) ? 1 : request.getPageNum();
        if (pageIndex == page1.getTotal()) {
            maps.put("more", false);
        } else {
            maps.put("more", true);
        }
        return maps;
    }
    /**
     * 保存当前行数据
     *
     * @param row
     */
    @Override
    public void saveFeeInfos(Row row) {
        FeeInfo feeInfo = new FeeInfo();
        feeInfo.setFeeCd(getValue(row.getCell((short) 0)));                        // 费率代码
        feeInfo.setPSeqNo(Integer.valueOf(getValue(row.getCell((short) 1))));        // 分段序号
        feeInfo.setFeeName(getValue(row.getCell((short) 2)));                        // 费率名称
        feeInfo.setCrtOrgId(getValue(row.getCell((short) 3)));                        // 所属机构代码
        feeInfo.setPStartValue(getValue(row.getCell((short) 4)));    // 起始金额
        feeInfo.setPEndValue(getValue(row.getCell((short) 5)));    // 结束金额
        feeInfo.setPCalType(getValue(row.getCell((short) 6)));                        // 计算方式
        String feeRate = getValue(row.getCell((short) 7));
        feeRate = feeRate.replace("%", "");                                        // 0.0005%记录进表是0.0005，后面其实还是有百分号的
        feeInfo.setPFeeRate(feeRate);                                // 费率值
        feeInfo.setPFeeRateMax(getValue(row.getCell((short) 8)));    // 费率封顶值
        feeInfo.setPFeeRateMin(getValue(row.getCell((short) 9)));    // 费率最小值
        feeInfo.setAuditStatus("01");                                                    // 状态（默认：新增-审批流程中）
        feeInfo.setImpStatus("00");                                                    // 费率状态（默认非正式）
//		feeInfo.setLogle("0");														// 修改标示
        // 保存数据
        this.saveOrUpdate(feeInfo);
    }
    /**
     * 获取单元格值
     *
     * @param cell
     * @return
     */
    public String getValue(Cell cell) {
        if (cell == null) {
            return "";
        } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            return String.valueOf(cell.getNumericCellValue());
        } else {
            return String.valueOf(cell.getStringCellValue());
        }
    }

    @Override
    @Transactional(value = "transactionManager")
    public OperationResult saveData(String optFlag, String oprMenuId, String oprMenuName, List<FeeInfo> feeInfoList, HttpServletRequest request, String webNextUrl) throws RedpException {
        Map<String, Object> result = com.google.common.collect.Maps.newHashMap();
        String lastUpddt = DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS");
        UpmpUserInfoVO user = CommonUtils.getCurrentUser(upmpSysParamService);
        FeeInfo entity=feeInfoList.get(0);
        String instId = entity.getInstId();
        UpmpOrganization org;
        if (optFlag.equals("add") && user.isAdmin()) {
            if (StringUtils.isEmpty(instId)) {
                log.error("保存数据时请先选择法人行!");
                return OperationResult.buildFailureResult("保存数据时请先选择法人行!");
            } else {
                org = organizationService.getHeadOrgByCode(instId);
            }
        } else {
            org = organizationService.getOrgByCode(user.getOrgCode(), user.getInstId());
        }
        String feeCd = feeInfoList.get(0).getFeeCd();
        String impStatus = feeInfoList.get(0).getImpStatus();
        String auditStatus = feeInfoList.get(0).getAuditStatus();

        if (PageOptFlagEnum.OPT_FLAG_ADD.getType().equals(optFlag)) {
            UpmpPrivilegeCheck privilegeCheck = upmpPrivilegeCheckService.getPrivilegeCheckByPrivilegeCode(user.getInstId(), "费率模板管理:新增");
            //
            List<BigDecimal> start = new ArrayList<>();
            List<BigDecimal> end = new ArrayList<>();
            for (FeeInfo feeInfo : feeInfoList) {
                start.add(new BigDecimal(feeInfo.getPStartValue()));
                end.add(new BigDecimal(feeInfo.getPEndValue()));
            }
            if (false == this.Fulltime(start, end)) {
                return OperationResult.buildFailureResult("按照分段规则填写");
            }
            feeCd = "FFES" + String.format("%06d", Integer.parseInt(upmpSysSeqService.updateParamValue("FEE_INFO", "FEE_CODE", "20")));
            if (null != privilegeCheck && BusinessContainer.YES.equals(privilegeCheck.getChecked())) {
                // 保存正式表
                for (int idx = 0; idx < feeInfoList.size(); idx++) {
                    FeeInfo feeInfo = feeInfoList.get(idx);
                    feeInfo.setId(null);
                    feeInfo.setFeeCd(feeCd);
                    feeInfo.setInstId(instId);
                    feeInfo.setPSeqNo(idx);
                    feeInfo.setStartDate(GetBeforeDate.getAfterDate());
                    feeInfo.setEndDate(BusinessContainer.doomsday);
                    feeInfo.setOprId(user.getId());
                    feeInfo.setCrtOrgId(org.getOrgCode());
                    feeInfo.setCreateTime(lastUpddt);
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);
                    feeInfo.setImpStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_CHECKING.getType());
                }
                this.mergeData(feeInfoList);
                // 保存临时表
                List<BizTmp> tmpList = new ArrayList<>();
                for (FeeInfo feeInfo : feeInfoList) {
                    BizTmp tmp = new BizTmp();
                    String bizData = JSON.toJSONString(feeInfo);
                    if(bizData.length()>12000){
                        throw new RedpException("业务数据过长，请联系管理员！");
                    }
                    String ename = feeInfo.getClass().getAnnotation(TableName.class).value();
                    String cname = feeInfo.getClass().getAnnotation(ApiModelProperty.class).value();
                    String bizData1;
                    String bizData2 = "";
                    String bizData3 = "";
                    if(bizData.length()>4000){
                        bizData1 = bizData.substring(0,3999);
                        bizData2 = bizData.substring(4000);
                    }else{
                        bizData1=bizData;
                    }
                    if(bizData2.length()>4000){
                        bizData2= bizData2.substring(0,3999);
                        bizData3=bizData.substring(8000);
                    }
                    tmp.setBizData1(bizData1);
                    tmp.setBizData2(bizData2);
                    tmp.setBizData3(bizData3);
                    tmp.setDetailFlag("Y");
                    tmp.setMasterKey(feeInfo.getFeeCd());
                    tmp.setBizOpr(BizOprEnum.OPR_ADD.getType());
                    tmp.setCreateTime(lastUpddt);
                    tmp.setLastOprId(user.getId());
                    tmp.setLastUpdateTime(lastUpddt);
                    tmp.setOprMenuId(oprMenuId);
                    tmp.setOprMenuName(oprMenuName);
                    tmp.setOprTableCname(cname);
                    tmp.setOprTableEname(ename);
                    tmp.setManageInstId(org.getOrgCode());
                    tmp.setInstId(instId);
                    tmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    tmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_CHECKING.getType());
                    if (Common.isBlank(tmp.getRealId())) {
                        tmp.setRealId(feeInfo.getId());
                    }
                    tmp.setWebNextUrl(webNextUrl);
                    tmpList.add(tmp);
                }
                //设置主记录
                tmpList.get(0).setDetailFlag("N");
                bizTmpService.saveOrUpdateBatch(tmpList);
            } else {
                // 保存正式表
                for (int idx = 0; idx < feeInfoList.size(); idx++) {
                    FeeInfo feeInfo = feeInfoList.get(idx);
                    feeInfo.setId(null);
                    feeInfo.setInstId(instId);
                    feeInfo.setFeeCd(feeCd);
                    feeInfo.setPSeqNo(idx);
                    feeInfo.setStartDate(GetBeforeDate.getAfterDate());
                    feeInfo.setEndDate(BusinessContainer.doomsday);
                    feeInfo.setOprId(user.getId());
                    feeInfo.setCrtOrgId(org.getOrgCode());
                    feeInfo.setCreateTime(lastUpddt);
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);
                    feeInfo.setImpStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_PASS.getType());
                }
                this.mergeData(feeInfoList);
                // 保存历史表
                for (FeeInfo feeInfo : feeInfoList) {
                    bizHisService.saveBizHisNew(feeInfo, new FeeInfo(), user, org.getInstId(), BizOprEnum.OPR_ADD.getType(), lastUpddt
                            , oprMenuId, oprMenuName, feeInfo.getId(),null,null,null);
                }
            }
        } else if (PageOptFlagEnum.OPT_FLAG_UPDATE.getType().equals(optFlag)) {
            List<UpmpBMchntFeeInfo> mchntList = bMchntFeeInfoService.getfee(feeCd);
            if (null != mchntList && mchntList.size() > 0) {
                return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
            }

            List<BigDecimal> start = new ArrayList<>();
            List<BigDecimal> end = new ArrayList<>();
            for (FeeInfo feeInfo : feeInfoList) {
                start.add(new BigDecimal(feeInfo.getPStartValue()));
                end.add(new BigDecimal(feeInfo.getPEndValue()));
            }
            if (!this.Fulltime(start, end)) {
                return OperationResult.buildFailureResult("按照分段规则填写");
            }
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
            String nowDate = sdfDate.format(new Date());
            UpmpPrivilegeCheck privilegeCheck = upmpPrivilegeCheckService.getPrivilegeCheckByPrivilegeCode(user.getInstId(), "费率模板管理:修改");
            if (null != privilegeCheck && BusinessContainer.YES.equals(privilegeCheck.getChecked())) {
                // 修改正式表状态
                this.upstatus(feeCd, BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType(), feeInfoList.get(0).getImpStatus(), user.getId(), lastUpddt,instId);
                // 将修改数据同步到临时表
//                List<FeeInfo> destFeeInfo = this.parseData(feeInfoList);
                String endDate = BusinessContainer.doomsday;
                List<BizTmp> tmpList = new ArrayList<>();
                for (FeeInfo feeInfo : feeInfoList) {
                    String uuid = CommonUtils.getUUID();
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType());
                    feeInfo.setStartDate(nowDate);
                    feeInfo.setEndDate(endDate);
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);

                    BizTmp tmp = new BizTmp();
                    String bizData = JSON.toJSONString(feeInfo);
                    if (bizData.length() > 12000) {
                        throw new RedpException("业务数据过长，请联系管理员！");
                    }
                    String ename = feeInfo.getClass().getAnnotation(TableName.class).value();
                    String cname = feeInfo.getClass().getAnnotation(ApiModelProperty.class).value();
                    String bizData1;
                    String bizData2 = "";
                    String bizData3 = "";
                    if(bizData.length()>4000){
                        bizData1 = bizData.substring(0,3999);
                        bizData2 = bizData.substring(4000);
                    }else{
                        bizData1=bizData;
                    }
                    if(bizData2.length()>4000){
                        bizData2= bizData2.substring(0,3999);
                        bizData3=bizData.substring(8000);
                    }
                    tmp.setBizData1(bizData1);
                    tmp.setBizData2(bizData2);
                    tmp.setBizData3(bizData3);
                    tmp.setDetailFlag("Y");
                    tmp.setMasterKey(feeInfo.getFeeCd());
                    tmp.setBizOpr(BizOprEnum.OPR_UPDATE.getType());
                    tmp.setCreateTime(lastUpddt);
                    tmp.setLastOprId(user.getId());
                    tmp.setLastUpdateTime(lastUpddt);
                    tmp.setOprMenuId(oprMenuId);
                    tmp.setOprMenuName(oprMenuName);
                    tmp.setOprTableCname(cname);
                    tmp.setOprTableEname(ename);
                    tmp.setManageInstId(org.getOrgCode());
                    tmp.setInstId(instId);
                    tmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    tmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType());
                    if (Common.isBlank(feeInfo.getId())) {
                        tmp.setRealId(uuid);
                    } else {
                        tmp.setRealId(feeInfo.getId());
                    }
                    tmp.setWebNextUrl(webNextUrl);
                    tmpList.add(tmp);
                }
                String ename = feeInfoList.get(0).getClass().getAnnotation(TableName.class).value();
                //新增、修改、删除临时表明细记录
                tmpList.get(0).setDetailFlag("N");
                this.BizTmpData(tmpList, instId, ename, feeInfoList.get(0).getFeeCd());
            } else {

                List<UpmpBMchntFeeInfo> ls = bMchntFeeInfoService.getfee(feeCd);
                if (null != ls && ls.size() > 0) {
                    return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
                }
                //正式表数据
                List<FeeInfo> oldfindfeeinfo = findcd(feeCd,instId);
                // 修改正式表
                for (int idx = 0; idx < feeInfoList.size(); idx++) {
                    FeeInfo feeInfo = feeInfoList.get(idx);
                    feeInfo.setInstId(instId);
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);
                    feeInfo.setStartDate(nowDate);
                    feeInfo.setEndDate(BusinessContainer.doomsday);
                    feeInfo.setImpStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_PASS.getType());
                }
                this.mergeData(feeInfoList);

                //历史表新增，将已修改数据录入至历史表
                List<FeeInfo> findcd = this.findcd(feeInfoList.get(0).getFeeCd(),feeInfoList.get(0).getInstId());
                this.BizHisData(feeInfoList, oldfindfeeinfo, user, org, oprMenuId, oprMenuName, lastUpddt);
            }
        } else if (PageOptFlagEnum.OPT_FLAG_CANCEL.getType().equals(optFlag)) {
            List<UpmpBMchntFeeInfo> mchntList = bMchntFeeInfoService.getfee(feeCd);
            if (null != mchntList && mchntList.size() > 0) {
                return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
            }
            /*// TODO: 商户费率功能调整完，用最新表结构来修改这个查询方法
                List<MerFeeR> ls = merFeeRService.getfee(feeCd);
                if (null != ls && ls.size() > 0) {
                    return OperationResult.buildFailureResult("存在使用此集团商户的正式商户，无法完成此操作");
                }*/
            List entitys = new ArrayList<>();
            List bizOpr = new ArrayList<>();
            List realIds = new ArrayList<>();
            UpmpPrivilegeCheck privilegeCheck = new UpmpPrivilegeCheck();

            List<UpmpBMchntFeeInfo> ls = bMchntFeeInfoService.getfee(feeCd);
            if (null != ls && ls.size() > 0) {
                return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
            }
            //正式表数据
            List<FeeInfo> findfeeinfo = findcd(feeCd,instId);
            //备份正式表数据
            List oldfindfeeinfo = findfeeinfo;
            privilegeCheck = upmpPrivilegeCheckService.getPrivilegeCheckByPrivilegeCode(user.getInstId(), "费率模板管理:注销");
            if (null != privilegeCheck && BusinessContainer.YES.equals(privilegeCheck.getChecked())) {
                //临时表数据
                String ename = feeInfoList.get(0).getClass().getAnnotation(TableName.class).value();
                List<BizTmp> bizTmpList = bizTmpService.getBizTmpByInstIdAndMasterKeyAndEname(instId, ename, feeInfoList.get(0).getFeeCd());

                //修改正式表审核状态为注销审批流程中
                for (FeeInfo feeInfo : findfeeinfo) {
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_CHECKING.getType());
                    feeInfo.setImpStatus(findfeeinfo.get(0).getImpStatus());
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);
                }
                this.saveOrUpdateBatch(findfeeinfo);
                List<BizTmp> tmpList = new ArrayList<>();
                for (FeeInfo feeInfo : feeInfoList) {
                    BizTmp tmp = new BizTmp();
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_CHECKING.getType());
                    feeInfo.setCancelReason(feeInfoList.get(0).getCancelReason());
                    String bizData = JSON.toJSONString(feeInfo);
                    if (bizData.length() > 12000) {
                        throw new RedpException("业务数据过长，请联系管理员！");
                    }
                    String cname = feeInfo.getClass().getAnnotation(ApiModelProperty.class).value();
                    String bizData1;
                    String bizData2 = "";
                    String bizData3 = "";
                    if(bizData.length()>4000){
                        bizData1 = bizData.substring(0,3999);
                        bizData2 = bizData.substring(4000);
                    }else{
                        bizData1=bizData;
                    }
                    if(bizData2.length()>4000){
                        bizData2= bizData2.substring(0,3999);
                        bizData3=bizData.substring(8000);
                    }
                    tmp.setBizData1(bizData1);
                    tmp.setBizData2(bizData2);
                    tmp.setBizData3(bizData3);
                    tmp.setDetailFlag("Y");
                    tmp.setMasterKey(feeInfo.getFeeCd());
                    tmp.setBizOpr(BizOprEnum.OPR_CANCEL.getType());
                    tmp.setCreateTime(lastUpddt);
                    tmp.setLastOprId(user.getId());
                    tmp.setLastUpdateTime(lastUpddt);
                    tmp.setOprMenuId(oprMenuId);
                    tmp.setOprMenuName(oprMenuName);
                    tmp.setOprTableCname(cname);
                    tmp.setOprTableEname(ename);
                    tmp.setManageInstId(org.getOrgCode());
                    tmp.setInstId(instId);
                    tmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    tmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_CHECKING.getType());
                    tmp.setRealId(feeInfo.getId());
                    tmp.setWebNextUrl(webNextUrl);
                    tmpList.add(tmp);
                }
                //新增、修改、删除临时表明细记录
                tmpList.get(0).setDetailFlag("N");
                this.BizTmpData(tmpList, instId, ename, feeInfoList.get(0).getFeeCd());

            } else {
                for (FeeInfo feeInfo : findfeeinfo) {
                    feeInfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_PASS.getType());
                    feeInfo.setImpStatus(BizDataStatusEnum.STATUS_CANCELED.getType());
                    feeInfo.setLastOprId(user.getId());
                    feeInfo.setLastUpdateTime(lastUpddt);
                    feeInfo.setCancelReason(feeInfoList.get(0).getCancelReason());
                    bizOpr.add(BizOprEnum.OPR_CANCEL.getType());
                    realIds.add(feeInfo.getId());
                }
                this.saveOrUpdateBatch(findfeeinfo);

                entitys = findfeeinfo;
                bizHisService.saveBizHisList(entitys, oldfindfeeinfo, user, org.getInstId(), bizOpr, lastUpddt, oprMenuId, oprMenuName, realIds,null,null,null);
            }
        } else if (PageOptFlagEnum.OPT_FLAG_CHECK.getType().equals(optFlag)) {
            //临时表数据
            String ename = feeInfoList.get(0).getClass().getAnnotation(TableName.class).value();
            List<BizTmp> bizTmpList = bizTmpService.getBizTmpByInstIdAndMasterKeyAndEname(instId, ename, feeInfoList.get(0).getFeeCd());
            List<FeeInfo> feeinfoNew = new ArrayList<>();
            //正式表数据
            List<FeeInfo> findfeeinfo = findcd(feeCd,instId);
            //备份正式表数据
            List oldfindfeeinfo = findfeeinfo;

            for (BizTmp biztmp : bizTmpList) {
                String bizdata = "";
                if (null != biztmp.getBizData1()) {
                    bizdata += biztmp.getBizData1();
                }
                if (null != biztmp.getBizData2()) {
                    bizdata += biztmp.getBizData2();
                }
                if (null != biztmp.getBizData3()) {
                    bizdata += biztmp.getBizData3();
                }
                FeeInfo feeinfo = JSON.parseObject(bizdata, FeeInfo.class);
                if (Common.isBlank(feeinfo.getId())) {
                    feeinfo.setId(biztmp.getRealId());
                }
                feeinfoNew.add(feeinfo);
            }

            String opt = request.getParameter("opt");
            if (Common.isBlank(opt)) {
                log.error("请求参数(opt)异常!");
                return OperationResult.buildFailureResult("请求参数(opt)异常!", result);
            }

            List entitys = new ArrayList<>();
            List bizOpr = new ArrayList<>();
            List realIds = new ArrayList<>();
            if (BizDataAuditStatusEnum.AUDIT_STATUS_ADD_CHECKING.getType().equals(feeInfoList.get(0).getAuditStatus())) {
                if (PageOptFlagEnum.OPT_FLAG_PASS.getType().equals(opt)) {
                    //修改临时表审核状态为新增审批通过
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_PASS.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //将临时表数据保存到正式表审核状态为新增审批通过数据状态为正式
                    for (FeeInfo feeinfo : feeinfoNew) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_PASS.getType());
                        feeinfo.setImpStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                        bizOpr.add(BizOprEnum.OPR_ADD.getType());
                        realIds.add(feeinfo.getId());
                    }
                    this.saveOrUpdateBatch(feeinfoNew);
                    //将正式表数据保存到临时表
                    entitys = feeinfoNew;
                    bizHisService.saveBizHisList(entitys, oldfindfeeinfo, user, org.getInstId(), bizOpr, lastUpddt, oprMenuId, oprMenuName, realIds,null,null,null);
                } else {
                    //修改临时表审核状态为新增审批拒绝
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_REJECT.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //修改正式表审核状态为新增审批拒绝
                    for (FeeInfo feeinfo : findfeeinfo) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_ADD_REJECT.getType());
                        feeinfo.setImpStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                        feeinfo.setAuditRefuseReason(feeInfoList.get(0).getAuditRefuseReason());
                    }
                    this.saveOrUpdateBatch(findfeeinfo);
                }
            } else if (BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_CHECKING.getType().equals(feeInfoList.get(0).getAuditStatus())) {
                if (PageOptFlagEnum.OPT_FLAG_PASS.getType().equals(opt)) {
                    List<UpmpBMchntFeeInfo> ls = bMchntFeeInfoService.getfee(feeCd);
                    if (null != ls && ls.size() > 0) {
                        return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
                    }
                    //修改临时表审核状态为注销审批通过
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_PASS.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_CANCELED.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //将临时表数据保存到正式表审核状态为注销审批通过
                    for (FeeInfo feeinfo : feeinfoNew) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_PASS.getType());
                        feeinfo.setImpStatus(BizDataStatusEnum.STATUS_CANCELED.getType());
                        bizOpr.add(BizOprEnum.OPR_CANCEL.getType());
                        realIds.add(feeinfo.getId());
                    }
                    this.saveOrUpdateBatch(feeinfoNew);
                    //将正式表数据保存到临时表
                    entitys = feeinfoNew;
                    bizHisService.saveBizHisList(entitys, oldfindfeeinfo, user, org.getInstId(), bizOpr, lastUpddt, oprMenuId, oprMenuName, realIds,null,null,null);
                } else {
                    //修改临时表审核状态为注销审批拒绝
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_REJECT.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //修改正式表审核状态为新增审批拒绝
                    for (FeeInfo feeinfo : findfeeinfo) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_CANCEL_REJECT.getType());
                        feeinfo.setImpStatus(feeInfoList.get(0).getImpStatus());
                        feeinfo.setAuditRefuseReason(feeInfoList.get(0).getAuditRefuseReason());
                    }
                    this.saveOrUpdateBatch(findfeeinfo);
                }
            } else if (BizDataAuditStatusEnum.AUDIT_STATUS_UPD_CHECKING.getType().equals(feeInfoList.get(0).getAuditStatus())) {
                if (PageOptFlagEnum.OPT_FLAG_PASS.getType().equals(opt)) {
                    List<UpmpBMchntFeeInfo> ls = bMchntFeeInfoService.getfee(feeCd);
                    if (null != ls && ls.size() > 0) {
                        return OperationResult.buildFailureResult("存在使用此费率信息的正式商户，无法完成此操作");
                    }
                    //修改临时表审核状态为修改审批通过
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_PASS.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //将临时表数据保存到正式表审核状态为修改审批通过
                    for (FeeInfo feeinfo : feeinfoNew) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_PASS.getType());
                        feeinfo.setImpStatus(BizDataStatusEnum.STATUS_NORMAL.getType());
                        bizOpr.add(BizOprEnum.OPR_UPDATE.getType());
                        realIds.add(feeinfo.getId());
                    }
                    this.mergeData(feeinfoNew);
                    BizHisData(feeinfoNew, findfeeinfo, user, org, oprMenuId, oprMenuName, lastUpddt);
                } else {
                    //修改临时表审核状态为修改审批拒绝
                    for (BizTmp biztmp : bizTmpList) {
                        biztmp.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_REJECT.getType());
                        biztmp.setBizStatus(BizDataStatusEnum.STATUS_DRAFT.getType());
                    }
                    bizTmpService.saveOrUpdateBatch(bizTmpList);
                    //修改正式表审核状态为修改审批拒绝
                    for (FeeInfo feeinfo : findfeeinfo) {
                        feeinfo.setAuditStatus(BizDataAuditStatusEnum.AUDIT_STATUS_UPD_REJECT.getType());
                        feeinfo.setImpStatus(feeInfoList.get(0).getImpStatus());
                        feeinfo.setAuditRefuseReason(feeInfoList.get(0).getAuditRefuseReason());
                    }
                    this.saveOrUpdateBatch(findfeeinfo);
                }
            }
        }

        return OperationResult.buildSuccessResult("数据保存处理完成", result);
    }
    /**
     * @param tmpList
     * @param instId
     * @param ename
     * @param feeCd
     */
    private void BizTmpData(List<BizTmp> tmpList, String instId, String ename, String feeCd) throws RedpException {
        List<BizTmp> listOrg = bizTmpService.getBizTmpByInstIdAndMasterKeyAndEname(instId, ename, feeCd);
        List<BizTmp> listDel = new ArrayList<>();//待删除的数据
        List<BizTmp> listNew = new ArrayList<>();//待新增的数据
        List<BizTmp> listUpd = new ArrayList<>();//待修改的数据

        if (null != listOrg) {
            Iterator<BizTmp> itMsir = listOrg.iterator();
            while (itMsir.hasNext()) {
                BizTmp msto = (BizTmp) itMsir.next();
                int flag = 0;

                Iterator<BizTmp> itMsi = tmpList.iterator();
                while (itMsi.hasNext()) {
                    BizTmp mst = (BizTmp) itMsi.next();
                    if (msto.getRealId().equals(mst.getRealId())) {
                        flag = 1;
                        listUpd.add(msto);
                        break;
                    }
                }
                if (flag == 0) { // 正式表的数据在临时表中已经不存在
                    listDel.add(msto);
                }
            }
        }

        if (null != tmpList) {//分析出待新增的数据
            Iterator<BizTmp> itMsir = tmpList.iterator();
            while (itMsir.hasNext()) {
                BizTmp mst = (BizTmp) itMsir.next();
                int flag = 0;

                Iterator<BizTmp> itMso = listOrg.iterator();
                while (itMso.hasNext()) {
                    BizTmp msto = (BizTmp) itMso.next();
                    if (msto.getRealId().equals(mst.getRealId())) {
                        flag = 1;
                        BeanUtils.copyProperties(mst, msto);
                        break;
                    }
                }
                if (flag == 0) { // 临时表中不存在的数据
                    listNew.add(mst);
                }
            }
        }
        bizTmpService.mergeBizTmps(listDel, listNew, listUpd);
    }
    /**
     * 新增、修改、删除历史表明细记录
     *
     * @param feeInfoList
     * @param oldfindfeeinfo
     * @param user
     * @param org
     * @param oprMenuId
     * @param oprMenuName
     * @param lastUpddt
     */
    private void BizHisData(List<FeeInfo> feeInfoList, List<FeeInfo> oldfindfeeinfo, UpmpUserInfoVO user, UpmpOrganization org, String oprMenuId, String oprMenuName, String lastUpddt) throws RedpException {
        List entitys = new ArrayList<>();
        List entityOlds = new ArrayList<>();
        List bizOpr = new ArrayList<>();
        List realIds = new ArrayList<>();

        if (null != oldfindfeeinfo) {
            Iterator<FeeInfo> itMsir = oldfindfeeinfo.iterator();
            while (itMsir.hasNext()) {
                FeeInfo msto = (FeeInfo) itMsir.next();
                int flag = 0;

                Iterator<FeeInfo> itMsi = feeInfoList.iterator();
                while (itMsi.hasNext()) {
                    FeeInfo mst = (FeeInfo) itMsi.next();
                    if (msto.getId().equals(mst.getId())) {
                        flag = 1;
                        break;
                    }
                }
                if (flag == 0) { // 正式表的数据在临时表中已经不存在
                    /*listDel.add(msto);*/
                    entitys.add(msto);
                    entityOlds.add(msto);
                    bizOpr.add(BizOprEnum.OPR_DELETE.getType());
                    realIds.add(msto.getId());
                }
            }
        }

        if (null != feeInfoList) {//分析出待新增的数据
            Iterator<FeeInfo> itMsir = feeInfoList.iterator();
            while (itMsir.hasNext()) {
                FeeInfo mst = (FeeInfo) itMsir.next();
                int flag = 0;

                Iterator<FeeInfo> itMso = oldfindfeeinfo.iterator();
                while (itMso.hasNext()) {
                    FeeInfo msto = (FeeInfo) itMso.next();
                    if (msto.getId().equals(mst.getId())) {
                        flag = 1;
                        BeanUtils.copyProperties(mst, msto);
                        break;
                    }
                }
                if (flag == 0) { // 临时表中不存在的数据
                    entitys.add(mst);
                    entityOlds.add(mst);
                    bizOpr.add(BizOprEnum.OPR_ADD.getType());
                    realIds.add(mst.getId());
                }
            }
        }

        for (int j = 0; j < oldfindfeeinfo.size(); j++) {
            for (int i = 0; i < feeInfoList.size(); i++) {
                if (feeInfoList.get(i).getId().equals(oldfindfeeinfo.get(j).getId())) {
                    entitys.add(feeInfoList.get(i));
                    entityOlds.add(oldfindfeeinfo.get(j));
                    bizOpr.add(BizOprEnum.OPR_UPDATE.getType());
                    realIds.add(oldfindfeeinfo.get(j).getId());
                }
            }
        }


        bizHisService.saveBizHisList(entitys, entityOlds, user, org.getInstId(), bizOpr, lastUpddt, oprMenuId, oprMenuName, realIds,null,null,null);
    }
    /**
     * 校验分段值是否以0开始，以99999999999999.99结束</br>
     * 符合规范返回true，否则返回false
     *
     * @param start 第一个分段值
     * @param end   最后一个分段值
     * @return
     */
    public boolean Fulltime(List<BigDecimal> start, List<BigDecimal> end) {
        Collections.sort(start);
        Collections.sort(end);

//        System.out.println("start : " + start);
//        System.out.println("end : " + end);

        try {
            BigDecimal first = start.get(0);
            BigDecimal last = end.get(end.size() - 1);
            BigDecimal max = new BigDecimal("99999999999999.99");
            int firstResult = first.compareTo(BigDecimal.ZERO);
            int lastResult = last.compareTo(max);
            if (firstResult != 0 || lastResult != 0) {
                return false;
            }
            // 逐项比较是否相等
            for (int i = 1; i < start.size(); i++) {
                if (start.get(i).compareTo(end.get(i - 1)) != 0) {
                    return false;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 新增、修改、删除明细记录
     *
     * @param feeInfoList
     * @throws RedpException
     */
    public void mergeData(List<FeeInfo> feeInfoList) throws RedpException {

        List<FeeInfo> listOrg = this.findcd(feeInfoList.get(0).getFeeCd(),feeInfoList.get(0).getInstId());
        List<FeeInfo> listDel = new ArrayList<>();//待删除的数据
        List<FeeInfo> listNew = new ArrayList<>();//待新增的数据
        List<FeeInfo> listUpd = new ArrayList<>();//待修改的数据

        if (null != listOrg) {
            Iterator<FeeInfo> itMsir = listOrg.iterator();
            while (itMsir.hasNext()) {
                FeeInfo msto = itMsir.next();
                int flag = 0;

                Iterator<FeeInfo> itMsi = feeInfoList.iterator();
                while (itMsi.hasNext()) {
                    FeeInfo mst = itMsi.next();
                    if (msto.getId().equals(mst.getId())) {
                        flag = 1;
                        break;
                    }
                }
                if (flag == 0) { // 正式表的数据在临时表中已经不存在
                    listDel.add(msto);
                }
            }
        }
        if (null != feeInfoList) {//分析出待新增的数据
            Iterator<FeeInfo> itMsir = feeInfoList.iterator();
            while (itMsir.hasNext()) {
                FeeInfo mst = itMsir.next();
                int flag = 0;

                Iterator<FeeInfo> itMso = listOrg.iterator();
                while (itMso.hasNext()) {
                    FeeInfo msto = itMso.next();
                    if (msto.getId().equals(mst.getId())) {
                        flag = 1;
                        BeanUtils.copyProperties(mst, msto);
                        listUpd.add(msto);
                        break;
                    }
                }
                if (flag == 0) { // 临时表中不存在的数据
                    mst.setId(null);
                    listNew.add(mst);
                }
            }
        }
        if (Common.isNotBlank(listDel) && listDel.size() > 0) {//删除
            for (FeeInfo feeInfo : listDel){
                this.baseMapper.deleteById(feeInfo.getId());
            }
        }
        if (Common.isNotBlank(listUpd) && listUpd.size() > 0) {//修改
            for (FeeInfo feeInfo : listUpd){
                this.updateById(feeInfo);
            }
        }
        if (Common.isNotBlank(listNew) && listNew.size() > 0) {//新增
            this.saveBatch(listNew);
        }
    }
    public void upstatus(String feecd, String auditStatus, String impStatus, String lastOprId, String lastUpdateTime,String instId) {
        this.upstatus(feecd, auditStatus, impStatus, lastOprId, lastUpdateTime, null,instId);
    }

    public void upstatus(String feecd, String auditStatus, String impStatus, String lastOprId, String lastUpdateTime, String auditRefuseReason,String instId) {
        String endDate = BusinessContainer.doomsday;
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
        String nowDate = sdfDate.format(new Date());
        LambdaUpdateWrapper<FeeInfo> wrapper= new LambdaUpdateWrapper<>();
        wrapper.eq(FeeInfo::getInstId,instId);
        wrapper.eq(FeeInfo::getFeeCd,feecd);
        FeeInfo info = new FeeInfo();
        info.setAuditStatus(auditStatus);
        info.setImpStatus(impStatus);
        info.setStartDate(nowDate);
        info.setEndDate(endDate);
        info.setLastOprId(lastOprId);
        info.setLastUpdateTime(lastUpdateTime);
        info.setAuditRefuseReason(auditRefuseReason);
        this.update(wrapper);
    }
}
